package sb.simple.socketio.service;

import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.HandshakeData;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DataListener;
import com.corundumstudio.socketio.listener.DisconnectListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sb.simple.socketio.pojo.PushMessage;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import static sb.simple.socketio.service.SocketIOService.Event.PUSH_EVENT;

/**
 * socketio能力具体实现
 */
@Service(value = "socketIOService")
public class SocketIOServiceImpl implements SocketIOService {

    // 用来存已连接的客户端
    private static Map<String, SocketIOClient> clientMap = new ConcurrentHashMap<>();

    @Autowired
    private SocketIOServer socketIOServer;

    /**
     * Spring IoC容器创建之后-在加载SocketIOServiceImpl Bean之后启动
     */
    @PostConstruct
    private void autoStartup() throws Exception {
        //start();
    }

    /**
     * Spring IoC容器在销毁SocketIOServiceImpl Bean之前关闭-避免重启项目服务端口占用问题
     */
    @PreDestroy
    private void autoStop() throws Exception {
        stop();
    }

    @Override
    public void start() throws Exception {
        //监听客户端连接
        socketIOServer.addConnectListener(new ConnectListener() {
            @Override
            public void onConnect(SocketIOClient client) {
                //clientId为客户端来参
                String clientId = getParamsByClient(client);
                if (clientId != null) {
                    System.out.println(clientId);
                    System.out.println("onConnect()-SessionId:" + client.getSessionId());
                    System.out.println("onConnect()-RemoteAddress:" + client.getRemoteAddress());
                    System.out.println("onConnect()-Transport:" + client.getTransport());
                    clientMap.put(clientId, client);
                }
            }
        });

        //监听客户端断开连接
        socketIOServer.addDisconnectListener(new DisconnectListener() {
            @Override
            public void onDisconnect(SocketIOClient client) {
                //clientId为客户端来参
                String clientId = getParamsByClient(client);
                if (clientId != null) {
                    clientMap.remove(clientId);
                    System.out.println("onDisconnect()-clientId:" + clientId);
                    System.out.println("onDisconnect()-SessionId:" + client.getSessionId());
                    client.disconnect();
                }
            }
        });

        //监听客户端的自定义事件
        socketIOServer.addEventListener("text", Object.class, new DataListener<Object>() {
            @Override
            public void onData(SocketIOClient client, Object data, AckRequest ackRequest) throws Exception {
                HandshakeData handshakeData = client.getHandshakeData();
                System.out.println("EventListener-onData()-handShakeData:" + handshakeData);

                //clientId为客户端来参
                String clientId = getParamsByClient(client);
                if (null != clientId) {
                    //收到的客户端消息
                    System.out.println("EventListener-onData()-data(客户端消息):" + data + ", 来自客户端clientId:" + clientId);

                    //推送给客户端的消息
                    Thread.sleep(new Random().nextInt(2000));
                    client.sendEvent(PUSH_EVENT, new Date().toLocaleString() + ", 服务端来消息啦, clientId:" + clientId);
                }
            }
        });

        socketIOServer.start();
    }


    @Override
    public void stop() {
        if (socketIOServer != null) {
            socketIOServer.stop();
            socketIOServer = null;
        }
    }

    @Override
    public void pushMessageToUser(PushMessage pushMessage) {
        String loginUserNum = pushMessage.getLoginUserNum();
        if (!loginUserNum.isEmpty()) {
            SocketIOClient client = clientMap.get(loginUserNum);
            if (client != null) client.sendEvent(PUSH_EVENT, pushMessage);
        }
    }


    /**
     * 获取client连接中的参数
     */
    private String getParamsByClient(SocketIOClient client) {
        Map<String, List<String>> params = client.getHandshakeData().getUrlParams();
        List<String> list = params.get("clientId");
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }
}